package com.xyy.saas.payment.adpater.jd.callback;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.adpater.jd.common.JDConstants;
import com.xyy.saas.payment.adpater.jd.utils.JDRequestUtils;
import com.xyy.saas.payment.adpater.jd.vo.JDAggregateNotifyRefundVo;
import com.xyy.saas.payment.adpater.jd.vo.JDAggregateNotifyTradeVo;
import com.xyy.saas.payment.adpater.pingxx.domain.PayDO;
import com.xyy.saas.payment.adpater.pingxx.domain.RefundDO;
import com.xyy.saas.payment.callback.core.handler.CastRequestHandler;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.cores.enums.JDPayTradeStatusEnum;
import com.xyy.saas.payment.dao.model.PrePayOrder;
import com.xyy.saas.payment.dao.model.RefundOrder;
import com.xyy.saas.payment.payment.core.service.PrePayOrderService;
import com.xyy.saas.payment.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 京东签约结果通知handler
 */
@Component
@Slf4j
public class CastJDPayAggrateRequestHandler implements CastRequestHandler {
    @Autowired
    private PrePayOrderService prePayOrderService;

    @Override
    public String getChannel() {
        return Constants.CHANNEL_JDAGGREGATE_NAME;
    }

    @Override
    public Object castRequestHandler(String method, Map<String, String> request, HttpServletRequest requestMsg) throws Exception {
        String body = request.get("post-val");
        JSONObject params = JSONObject.parseObject(body);
        log.info("jdCardAggratePayCallBack接收到京东结果通知：解密前数据为 {}", params);
        // 支付
        if (Constants.METHOD_PAY_SUCCESS_NAME.equals(method)) {
            return castToPayDO(body, params);
        }
        // 退款
        if (Constants.METHOD_REFUND_SUCCESS.equals(method)) {
            return castToRefundDO(body, params);
        }
        throw new UnsupportedOperationException("Not support JD callback method " + method);
    }

    /**
     * 退款：转换为退款结果通知
     */
    private RefundDO castToRefundDO(String body, JSONObject params) throws Exception {
        String logPrefix = "jdAggratePayCastToRefundDO ";
        JSONObject jsonObject = JDRequestUtils.verifySignAndReturn(logPrefix, params.getString("merchantNo"), body);
        log.info("{} 接收到京东聚合退款结果通知：解密后数据为 {}", logPrefix, jsonObject);
        JDAggregateNotifyRefundVo jdNotifyRefundVo = JSON.toJavaObject(jsonObject, JDAggregateNotifyRefundVo.class);
        if (!JDConstants.SUCCESS_CODE.equals(jdNotifyRefundVo.getResultCode()) || !JDPayTradeStatusEnum.effectiveStatus(jdNotifyRefundVo.getTradeStatus())) {
            log.error("{} 交易状态错误！", logPrefix);
            throw new Exception("交易状态错误！");
        }
        RefundDO refundDO = new RefundDO();
        // 基本参数
        refundDO.setRefundNo(jdNotifyRefundVo.getOutTradeNo());
        refundDO.setId(jdNotifyRefundVo.getTradeNo());
        refundDO.setOrderNo(jdNotifyRefundVo.getOriginalOutTradeNo());
        refundDO.setSucceed("SUCCESS".equalsIgnoreCase(CastJDPayRequestHandler.transTradeStatus(jdNotifyRefundVo.getTradeStatus())) ? true : false);
        refundDO.setStatus(refundDO.getSucceed() ? RefundOrder.STATUS_FINISH : RefundOrder.STATUS_FAIL);
        refundDO.setTimeSucceed(StringUtils.isBlank(jdNotifyRefundVo.getFinishDate()) ? null : DateUtil.parase(jdNotifyRefundVo.getFinishDate(), DateUtil.YYYYMMDDHHMMSS));
        refundDO.setFailureCode(jdNotifyRefundVo.getResultCode() + "|" + jdNotifyRefundVo.getResultDesc());
        refundDO.setFailureMsg(jdNotifyRefundVo.getResultDesc());
        return refundDO;
    }

    /**
     * 支付：转换为支付结果通知
     */
    private PayDO castToPayDO(String body, JSONObject params) throws Exception {
        String logPrefix = "jdAggratePaycastToPayDO ";
        JSONObject jsonObject = JDRequestUtils.verifySignAndReturn(logPrefix, params.getString("merchantNo"), body);
        log.info("{}接收到京东支付结果通知：解密后数据为 {}", logPrefix, jsonObject);
        JDAggregateNotifyTradeVo jdNotifyTradeVo = JSON.toJavaObject(jsonObject, JDAggregateNotifyTradeVo.class);
        if (!JDConstants.SUCCESS_CODE.equals(jdNotifyTradeVo.getResultCode()) || !JDPayTradeStatusEnum.effectiveStatus(jdNotifyTradeVo.getTradeStatus())) {
            log.error("{} 交易状态错误！", logPrefix);
            throw new Exception("交易状态错误！");
        }
        // 查询预支付订单
        PrePayOrder prePayOrder = prePayOrderService.getPrePayOrderByPayNo(jdNotifyTradeVo.getOutTradeNo());
        JSONObject extra = (StringUtils.isBlank(prePayOrder.getExtra()) ? new JSONObject() : JSONObject.parseObject(prePayOrder.getExtra()));
        // 基本参数
        PayDO payDO = new PayDO();
        payDO.setMchId(params.getString("merchantNo"));
        payDO.setOrderNo(jdNotifyTradeVo.getOutTradeNo());
        payDO.setChannelChargeNo(jdNotifyTradeVo.getTradeNo());
        payDO.setAmount(jdNotifyTradeVo.getTradeAmount());
        payDO.setChannel(Constants.CHANNEL_JDAGGREGATE_NAME + "_" + jdNotifyTradeVo.getPayTool().toLowerCase());
        payDO.setPayMode(extra.getString("payMode"));
        payDO.setResultCode(CastJDPayRequestHandler.transTradeStatus(jdNotifyTradeVo.getTradeStatus()));
        payDO.setChannelTransactionNo(jdNotifyTradeVo.getTradeNo());
        payDO.setTimePaid(StringUtils.isBlank(jdNotifyTradeVo.getFinishDate()) ? null : DateUtil.parase(jdNotifyTradeVo.getFinishDate(), DateUtil.YYYYMMDDHHMMSS));
        payDO.setFailureCode(jdNotifyTradeVo.getResultCode() + "|" + jdNotifyTradeVo.getResultDesc());
        payDO.setFailureMsg(jdNotifyTradeVo.getResultDesc());
        // 其他参数
        payDO.setNotifyTime(DateUtil.now());
        payDO.setFailureCode(jdNotifyTradeVo.getResultCode());
        payDO.setFailureMsg(jdNotifyTradeVo.getResultDesc());
        payDO.setReturnCode(jdNotifyTradeVo.getResultCode());
        payDO.setCount(0);
        payDO.setExtra(prePayOrder.getExtra());
        payDO.setBusinessType(prePayOrder.getBusinessType());
        payDO.setBusinessOrderType(prePayOrder.getBusinessOrderType());
        payDO.setReceiverId(prePayOrder.getReceiverId());
        payDO.setCallbackAddress(prePayOrder.getCallbackAddress());
        payDO.setPayer(prePayOrder.getPayer());
        return payDO;
    }

}
